home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / applic / ncsa / Mac / Telnet2.6 / prerelease / d5 / Telnet 2.6.1d5.src.sit.hqx / Telnet 2.6.1d5 src / source / rs / drag.c next >
Encoding:
C/C++ Source or Header  |  1995-01-22  |  10.4 KB  |  394 lines

  1. /****************************************************************
  2. *    NCSA Telnet for the Macintosh                                *
  3. *                                                                *
  4. *    National Center for Supercomputing Applications                *
  5. *    Software Development Group                                    *
  6. *    152 Computing Applications Building                            *
  7. *    605 E. Springfield Ave.                                        *
  8. *    Champaign, IL  61820                                        *
  9. *                                                                *
  10. *    Copyright (c) 1986-1994,                                    *
  11. *    Board of Trustees of the University of Illinois                *
  12. ****************************************************************/
  13.  
  14. #include <Drag.h>
  15. #include <Gestalt.h>
  16. #include <CodeFragments.h>
  17.  
  18. #include "TelnetHeader.h"
  19. #include "wind.h"
  20.  
  21. #include "maclook.proto.h"        // For WindowPtr2WindRecPtr proto
  22. #include "rsinterf.proto.h"
  23. #include "parse.proto.h"
  24. #include "drag.proto.h"
  25.  
  26. #ifdef MPW
  27. #pragma segment RS
  28. #endif
  29.  
  30. Boolean    gHaveDragMgr, gDropcanAcceptItems, gDropcursorInContent, gDropDestCanAcceptItems;
  31.  
  32. #define    kScrollbarSize    15
  33.  
  34. pascal OSErr MyReceiveDropHandler(WindowPtr theWindow, unsigned long handlerRefCon,
  35.                                   DragReference theDrag);
  36. PROTO_UPP(MyReceiveDropHandler, DragReceiveHandler);
  37. pascal OSErr MyTrackingHandler(short message, WindowPtr theWindow,
  38.                                void *handlerRefCon, DragReference theDrag);
  39. PROTO_UPP(MyTrackingHandler, DragTrackingHandler);
  40.  
  41. static    void LocalToGlobalRgn (RgnHandle rgn);
  42. static    void OutlineRegion (RgnHandle theRgn);
  43.  
  44. void    MyDragInit(void)
  45. {
  46.     OSErr    err;
  47.     long    dragMgrAttr;
  48.     
  49.     err = Gestalt(gestaltDragMgrAttr, &dragMgrAttr);
  50.     gHaveDragMgr = (err == noErr) && (dragMgrAttr & (1L << gestaltDragMgrPresent)) != 0;
  51.     #ifdef powerc
  52.     gHaveDragMgr = gHaveDragMgr && 
  53.         (dragMgrAttr & (1L << gestaltPPCDragLibPresent)) != 0
  54.         && ((long) InstallTrackingHandler) != kUnresolvedSymbolAddress;
  55.  
  56.  
  57.     #endif
  58.     // If the DragManager is available, install our tracking handlers
  59.     if (gHaveDragMgr) {
  60.         err = InstallTrackingHandler(MyTrackingHandlerUPP, nil, nil);
  61.  
  62.         if (err == noErr) {
  63.             // If all is ok so far, install the rcv handler
  64.             err = InstallReceiveHandler(MyReceiveDropHandlerUPP, nil, nil);
  65.             if (err != noErr) {
  66.                 // If an error ocurred installing the rcv handler, remove the tracking handler
  67.                 RemoveTrackingHandler(MyTrackingHandlerUPP, nil);
  68.                 }
  69.             }
  70.         
  71.         // If any error occurred, turn off DragManager support    
  72.         if (err != noErr) {
  73.             gHaveDragMgr = false;
  74.             }
  75.         }
  76. }
  77.  
  78. /*    MyReceiveDropHandler
  79.  *    Called by the Drag Manager when a drop occurs over one of Telnet's windows. */
  80. SIMPLE_UPP(MyReceiveDropHandler, DragReceiveHandler);
  81. pascal OSErr MyReceiveDropHandler(WindowPtr theWindow, unsigned long handlerRefCon,
  82.                                   DragReference theDrag)
  83. {    
  84.     OSErr                result;
  85.     Handle                dataH;
  86.     unsigned short        items, index;
  87.     ItemReference        theItem;
  88.     DragAttributes        attributes;
  89.     Size                textSize;
  90.     short                mouseDownModifiers, mouseUpModifiers;
  91.     WindRecPtr            tw;
  92.  
  93.     if (!gDropcanAcceptItems || !gDropcursorInContent)
  94.         return(dragNotAcceptedErr);
  95.  
  96.     SetPort(theWindow);
  97.  
  98.     // No text yet
  99.     dataH = nil;
  100.     
  101.     GetDragAttributes(theDrag, &attributes);
  102.     GetDragModifiers(theDrag, 0L, &mouseDownModifiers, &mouseUpModifiers);
  103.  
  104.     //    Loop through all of the drag items contained in this drag and collect the text
  105.     //    into the accumulation handle.
  106.  
  107.     CountDragItems(theDrag, &items);
  108.  
  109.     for (index = 1; index <= items; index++) {
  110.         //    Get the item's reference number, so we can refer to it.
  111.         GetDragItemReferenceNumber(theDrag, index, &theItem);
  112.  
  113.         //    Try to get the flags for a 'TEXT' flavor. If this returns noErr,
  114.         //    then we know that a 'TEXT' flavor exists in the item.
  115.         result = GetFlavorDataSize(theDrag, theItem, 'TEXT', &textSize);
  116.  
  117.         if (result == noErr) {
  118.             if (dataH == nil) {                    // No data yet, create a new handle for accumulation
  119.                 dataH = NewHandle(textSize);
  120.                 if (dataH == nil) {
  121.                     return memFullErr;            // Exit if there is an error
  122.                     }
  123.                 }
  124.             else {                                // Append to existing TEXT data
  125.                 SetHandleSize(dataH, GetHandleSize(dataH) + textSize);    // Grow the handle
  126.                 if (MemError() != noErr) {
  127.                     return memFullErr;            // Exit if there is a problem
  128.                     }
  129.                 }
  130.                 
  131.  
  132.             // Temporarily lock down the accumlation handle
  133.             HLock(dataH);
  134.         
  135.             // Get the drag data    
  136.             GetFlavorData(theDrag, theItem, 'TEXT', *dataH, &textSize, 0L);
  137.  
  138.             // Ok to unlock the accumulation handle
  139.             HUnlock(dataH);
  140.             }
  141.         }
  142.  
  143.     // Get the length of all that was accumulated
  144.     textSize = GetHandleSize(dataH);
  145.  
  146.     //    If we actually received text, insert it into the destination.
  147.     if (textSize != 0) {
  148.         if (attributes & dragHasLeftSenderWindow) {
  149.             HideDragHilite(theDrag);
  150.             }
  151.  
  152.         HLock(dataH);
  153.  
  154.         // Send the text to the window.        
  155.         tw = WindowPtr2WindRecPtr(theWindow);
  156.         if (tw != nil) {
  157.             SendStringAsIfTyped(tw, *dataH, textSize);
  158.             }
  159.         HUnlock(dataH);
  160.         }
  161.  
  162.     if (dataH != nil) {
  163.         DisposeHandle(dataH);
  164.         }
  165.  
  166.     return(noErr);
  167. }
  168.  
  169. /*    MyTrackingHandler
  170.  *    This is the drag tracking handler for windows in the DragText application.*/
  171. SIMPLE_UPP(MyTrackingHandler, DragTrackingHandler);
  172. pascal OSErr MyTrackingHandler(short message, WindowPtr theWindow,
  173.                                void *handlerRefCon, DragReference theDrag)
  174. {
  175.     short                result;
  176.     unsigned short        count, index;
  177.     unsigned long        flavorFlags, attributes;
  178.     ItemReference        theItem;
  179.     RgnHandle            theRgn, selectionRgn;
  180.     Point                theMouse, localMouse;
  181.     Rect                dragRect;
  182.     GrafPtr                savePort;
  183.     Boolean                inOriginalSelection;
  184.     
  185.     if ((message != dragTrackingEnterHandler) && (!gDropcanAcceptItems))
  186.         return(noErr);
  187.  
  188.     if ((message != dragTrackingEnterHandler) && (message != dragTrackingEnterWindow) 
  189.             && (!gDropDestCanAcceptItems))
  190.         return(noErr);
  191.  
  192.     GetDragAttributes(theDrag, &attributes);
  193.  
  194.     switch (message) {
  195.  
  196.         case dragTrackingEnterHandler:
  197.             //    We get called with this message the first time that a drag enters ANY
  198.             //    window in our application. 
  199.             gDropcanAcceptItems = true;
  200.                                         
  201.             //    Check to see if all of the drag items contain
  202.             //    TEXT. We only accept a drag if all of the items in the drag can be accepted.
  203.             CountDragItems(theDrag, &count);
  204.  
  205.             for (index = 1; index <= count; index++) {
  206.                 GetDragItemReferenceNumber(theDrag, index, &theItem);
  207.  
  208.                 result = GetFlavorFlags(theDrag, theItem, 'TEXT', &flavorFlags);
  209.  
  210.                 if (result != noErr) {
  211.                     gDropcanAcceptItems = false;
  212.                     break;
  213.                     }
  214.                 }
  215.             break;
  216.  
  217.         case dragTrackingEnterWindow:
  218.             //    We receive an EnterWindow message each time a drag enters one of our
  219.             //    application's windows. We initialize our global variables for tracking
  220.             //    the drag through the window.
  221.  
  222.             // Assume this window can accept the drag
  223.             gDropDestCanAcceptItems = true;
  224.             
  225.             // If it is not a connection window, it cannot accept a drop.
  226.             if (((WindowPeek)theWindow)->windowKind != WIN_CNXN) {
  227.                 gDropDestCanAcceptItems = false;
  228.                 break;
  229.                 }
  230.             
  231.             // Initially no blue box.
  232.             gDropcursorInContent = false;
  233.             break;
  234.  
  235.         case dragTrackingInWindow:
  236.             GetPort(&savePort);
  237.             SetPort(theWindow);
  238.  
  239.             //    We receive InWindow messages as long as the mouse is in one of our windows
  240.             //    during a drag. We draw the window highlighting when we get these messages.
  241.             GetDragMouse(theDrag, &theMouse, 0L);
  242.  
  243.             //    If we are still in the sender window, check to see if we should draw a blue box.
  244.             //    inOriginalSelection is true if the mouse is still within the confines of the
  245.             //    selected text's original location.  This allows the user to cancel a drop by
  246.             //    dropping the text somewhere inside of the original selection.
  247.             if (attributes & dragInsideSenderWindow) {
  248.                 localMouse = theMouse;
  249.                 GlobalToLocal(&localMouse);
  250.                 
  251.                 selectionRgn = RSGetTextSelRgn(WindowPtr2WindRecPtr(theWindow)->vs);
  252.                 inOriginalSelection = PtInRgn(localMouse, selectionRgn);
  253.                 DisposeRgn(selectionRgn);
  254.                 }
  255.             else {
  256.                 inOriginalSelection = false;
  257.                 }
  258.  
  259.             //    Show or hide the window highlighting when the mouse enters or leaves the
  260.             //    text area in our window (we don't want to show the highlighting when
  261.             //    the mouse is over the scroll bars).
  262.             dragRect = (*(((WindowPeek)theWindow)->contRgn))->rgnBBox;
  263.             
  264.             //    Subtract out the scrollbars.
  265.             dragRect.right -= kScrollbarSize;
  266.             dragRect.bottom -= kScrollbarSize;
  267.             
  268.             //    If the mouse is in the text area and not in the original selection,
  269.             //    draw the blue box.            
  270.             if (PtInRect(theMouse, &dragRect) && !inOriginalSelection) {
  271.                 if (!gDropcursorInContent) {
  272.  
  273.                     // Set up the blue box region.
  274.                     GlobalToLocal(&topLeft(dragRect));
  275.                     GlobalToLocal(&botRight(dragRect));
  276.                     RectRgn(theRgn = NewRgn(), &dragRect);
  277.  
  278.                     ShowDragHilite(theDrag, theRgn, true);
  279.  
  280.                     DisposeRgn(theRgn);
  281.                     }
  282.                     
  283.                 // Remember that we are in a valid drop location.
  284.                 gDropcursorInContent = true;
  285.  
  286.                 }
  287.             else {
  288.                 // We have moved out of a valid drop region.
  289.  
  290.                 if (gDropcursorInContent) {            // Hide the box if it was drawn.
  291.                     HideDragHilite(theDrag);
  292.                     }
  293.                     
  294.                 // Remember that we are outside of a valid drop region.
  295.                 gDropcursorInContent = false;
  296.  
  297.                 }    
  298.  
  299.             SetPort(savePort);
  300.             break;
  301.  
  302.         case dragTrackingLeaveWindow:
  303.                 HideDragHilite(theDrag);
  304.             break;
  305.  
  306.         case dragTrackingLeaveHandler:
  307.             break;
  308.  
  309.     }
  310.  
  311.     return(noErr);
  312. }
  313.  
  314. OSErr DragText(EventRecord *ev, Point where, short w, Boolean *dragged)
  315. {
  316.     DragReference    dragRef;
  317.     OSErr            err = noErr;
  318.     Boolean            haveDragRef = false;
  319.     RgnHandle        dragRgn = nil;
  320.     Handle            textH = nil;
  321.     long            size;
  322.     
  323.     *dragged = false;
  324.     if (!gHaveDragMgr) {
  325.         return noErr;
  326.         }
  327.         
  328.     dragRgn = RSGetTextSelRgn(w);
  329.     if (dragRgn == nil) {
  330.         return noErr;
  331.         }
  332.     if (!PtInRgn(where, dragRgn)) {
  333.         DisposeRgn(dragRgn);
  334.         return noErr;
  335.         }
  336.     if (!WaitMouseMoved(ev->where)) return noErr;
  337.     *dragged = true;
  338.  
  339.     textH = RSGetTextSel(w, 0);
  340.     
  341.     if ((textH == (char **)-1L) || (textH == nil)) {
  342.         textH = nil;
  343.         goto exit;
  344.         }
  345.     
  346.     HLock(textH);
  347.     size = GetHandleSize(textH);
  348.     
  349.     err = NewDrag(&dragRef);
  350.     if (err != noErr) goto exit;
  351.     haveDragRef = true;
  352.  
  353.     err = AddDragItemFlavor(dragRef, 1, 'TEXT', *textH, size, 0);
  354.     if (err != noErr) goto exit;
  355.  
  356.     LocalToGlobalRgn(dragRgn);
  357.     OutlineRegion(dragRgn);
  358.  
  359.     err = TrackDrag(dragRef, ev, dragRgn);
  360.     if (err != noErr && err != userCanceledErr) goto exit;
  361.  
  362.     DisposeRgn(dragRgn);
  363.     DisposeDrag(dragRef);
  364.     DisposeHandle(textH);
  365.     return noErr;
  366.     
  367. exit:
  368.  
  369.     if (haveDragRef) DisposeDrag(dragRef);
  370.     if (dragRgn != nil) DisposeRgn(dragRgn);
  371.     if (textH != nil) DisposeHandle(textH);
  372.     return err;
  373. }
  374.  
  375. static    void LocalToGlobalRgn (RgnHandle rgn)
  376. {
  377.     Point where;
  378.     
  379.     SetPt(&where, 0, 0);
  380.     LocalToGlobal(&where);
  381.     OffsetRgn(rgn, where.h, where.v);
  382. }
  383.  
  384. static    void OutlineRegion (RgnHandle theRgn)
  385. {
  386.     RgnHandle tempRgn;
  387.     
  388.     tempRgn = NewRgn();
  389.     CopyRgn(theRgn, tempRgn);
  390.     InsetRgn(tempRgn, 1, 1);
  391.     DiffRgn(theRgn, tempRgn, theRgn);
  392.     DisposeRgn(tempRgn);
  393. }
  394.